package cn.cagurzhan.service;

import cn.cagurzhan.common.constant.CacheConstants;
import cn.cagurzhan.common.constant.CommandNameConstants;
import cn.cagurzhan.common.constant.CommandPropertiesConstants;
import cn.cagurzhan.common.constant.ServiceConstant;
import cn.cagurzhan.domain.BaseEntity;
import cn.cagurzhan.domain.R;
import cn.cagurzhan.domain.dto.CommandResultDto;
import cn.cagurzhan.domain.entity.HomeLog;
import cn.cagurzhan.domain.entity.OperLog;
import cn.cagurzhan.domain.entity.User;
import cn.cagurzhan.domain.event.HomeLogEvent;
import cn.cagurzhan.domain.vo.ShouyeVo;
import cn.cagurzhan.mapper.UserMapper;
import cn.cagurzhan.utils.BeanCopyUtils;
import cn.cagurzhan.utils.ServletUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author AjaxZhan
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class AgriService {
    private static final String DEVICE_ID_ARGI = "65edb674fb8177243a4d9ad3_ESP32_WROOM";

    private final IoTService ioTService;

    private final CacheService cacheService;

    private final UserMapper userMapper;

    /**
     * 功能：【获取】首页信息
     * 描述：直接从华为云拿到设备影子，封装后返回
     */
    public R<Map<String,Object>> info(){
        // 拿到设备影子
        IoTDAClient client = ioTService.initClient();
        Map<String, Object> deviceShadowProperties = ioTService.getDeviceShadowProperties(client, DEVICE_ID_ARGI);
        log.info("远程调用：{}，拿到设备影子：{}","info", JSON.toJSONString(deviceShadowProperties));
        // 封装
        return R.ok(deviceShadowProperties);
    }


    public R<Void> shade(Integer power) {

        IoTDAClient client = ioTService.initClient();
        // 构造请求参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("sha_power", power);
        // 发送请求
        CommandResultDto commandResultDto =
                ioTService.sendCommand(client, DEVICE_ID_ARGI, ServiceConstant.AGRI_CONTROL,
                        "scontrol", params);
        log.info("远程调用：{}，得到返回值：{}","scontrol",JSON.toJSONString(commandResultDto));
        HomeLogEvent log = new HomeLogEvent();
        log.setType("调整遮阳设备角度为"+power);
        recordOpLog(log);
        return R.ok();
    }

    public R<Void> fans(Integer state) {
        IoTDAClient client = ioTService.initClient();
        // 构造请求参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("fans_PWM", state);
        // 发送请求
        CommandResultDto commandResultDto =
                ioTService.sendCommand(client, DEVICE_ID_ARGI, ServiceConstant.AGRI_CONTROL,
                        "fans_control", params);
        log.info("远程调用：{}，得到返回值：{}","fans_control",JSON.toJSONString(commandResultDto));
        HomeLogEvent log = new HomeLogEvent();
        log.setType("调整风机大小为"+state);
        recordOpLog(log);
        return R.ok();
    }

    public R<Void> guangai(Integer which, Integer power) {
        IoTDAClient client = ioTService.initClient();
        // 构造请求参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("water_power",power);
        if(which == 0){
            // 发送请求
            CommandResultDto commandResultDto =
                    ioTService.sendCommand(client, DEVICE_ID_ARGI, ServiceConstant.AGRI_CONTROL,
                            "lirrigate", params);
            log.info("远程调用：{}，得到返回值：{}","lirrigate",JSON.toJSONString(commandResultDto));
            HomeLogEvent log = new HomeLogEvent();
            log.setType("调整水泵1的出水量为"+power);
            recordOpLog(log);

        }else{
            // 发送请求
            CommandResultDto commandResultDto =
                    ioTService.sendCommand(client, DEVICE_ID_ARGI, ServiceConstant.AGRI_CONTROL,
                            "hirrigate", params);
            log.info("远程调用：{}，得到返回值：{}","hirrigate",JSON.toJSONString(commandResultDto));
            HomeLogEvent log = new HomeLogEvent();
            log.setType("调整水泵2的出水量为"+power);
            recordOpLog(log);
        }
        return R.ok();
    }

    /**
     * 调节LED
     */
    public R<Void> light(Integer red, Integer green) {
        IoTDAClient client = ioTService.initClient();
        // 构造请求参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("Red_Blue", red);
        params.put("White_Green",green);
        // 发送请求
        CommandResultDto commandResultDto =
                ioTService.sendCommand(client, DEVICE_ID_ARGI, ServiceConstant.AGRI_CONTROL,
                        "RGB_control", params);
        log.info("远程调用：{}，得到返回值：{}","RGB_control",JSON.toJSONString(commandResultDto));

        HomeLogEvent log = new HomeLogEvent();
        log.setType("调整大棚红灯为"+red + ",调整大棚绿灯为"+ green);
        recordOpLog(log);
        return R.ok();
    }

    /**
     * 返回所有日志消息
     */
    public R<List<OperLog>> listLog() {
        ArrayList<OperLog> operLogs = new ArrayList<>();
        // 从Redis中拿出数据
        List<String> jsons = cacheService.lRange("agri-log", 0, 15);
        for (String json : jsons) {
            operLogs.add(JSON.parseObject(json, OperLog.class));
        }
        return R.ok(operLogs);
    }


    /**
     * 直接将操作日志存入Redis
     */
    private void recordOpLog(HomeLogEvent homeLogEvent) {
        // 获取用户ID
        String userId = ServletUtils.getRequest().getHeader("user-id");
        log.warn("正在记录操作日志, userId={}", userId);
        User user = null;
        if (userId != null) {
            // 查询用户
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(User::getNickname).eq(User::getUserId, Long.valueOf(userId));
            user = userMapper.selectById(Long.valueOf(userId));
        } else {
            user = new User();
            user.setNickname("系统用户");
        }

        // 新增操作日志
        OperLog operLog = new OperLog();
        operLog.setLogBy(user.getNickname());
        operLog.setType(homeLogEvent.getType());
        operLog.setDelFlag(0);
        operLog.setLogTime(new Date());
        // 存入Redis
        cacheService.lLeftPush("agri-log",JSON.toJSONString(operLog));
    }
}
